﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using PearTunes.Client.PearTunesServiceReference;

using NAudio;
using NAudio.Wave;
using NAudio.CoreAudioApi;
using System.Threading;
using System.ComponentModel;
using System.IO;

namespace PearTunes.Client
{

    public partial class MainWindow : Window
    {
        static bool succesfullLogin = false;
        IWavePlayer waveOutDevice;
        WaveStream mainOutputStream;
        WaveChannel32 volumeStream;

        BackgroundWorker musicInfoUpdater = new BackgroundWorker();

        PlayListManager playListManager = new PlayListManager();
        PlayList currentPlaylist;

        enum Views
        {
            simpleList = 1,
            listWithCovers = 2,
            listWithCoverFlow = 3
        }

        Views preferredView = Views.simpleList;

        /// <summary>
        /// Constructs the main window for PearTunes
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
            waveOutDevice = new NAudio.Wave.DirectSoundOut();

            musicInfo.trackSlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(trackSlider_ValueChanged);

            musicInfoUpdater.DoWork += new DoWorkEventHandler(worker_DoWork);
            musicInfoUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
            musicInfoUpdater.WorkerSupportsCancellation = true;
            musicInfoUpdater.RunWorkerAsync();

            viewSelector.listSelect.MouseDown += new MouseButtonEventHandler(listSelect_MouseDown);
            viewSelector.listwithcoverSelect.MouseDown += new MouseButtonEventHandler(listwithcoverSelect_MouseDown);
            viewSelector.coverflowSelect.MouseDown += new MouseButtonEventHandler(coverflowSelect_MouseDown);

            RefreshPlaylistButtons();



        }

        #region User playlistjei
        private void RefreshPlaylistButtons()
        {
            playlistPanel.Children.Clear();

            if (playListManager.UserPlayListCount == 0)
            {
                RadioButton noUserPlaylistsButton = new RadioButton();
                noUserPlaylistsButton.Content = "Nincsenek lejátszási listák";
                noUserPlaylistsButton.GroupName = "mainGroup";
                noUserPlaylistsButton.IsEnabled = false;
                noUserPlaylistsButton.Style = (Style)FindResource("PlaylistRadioButtonStyle");
                playlistPanel.Children.Add(noUserPlaylistsButton);
            }
            else
            {

                for (int i = 0; i < playListManager.UserPlayListCount; i++)
                {
                    RadioButton playlistButton = new RadioButton();
                    playlistButton.Content = playListManager.GetUserPlayListAt(i).Name;
                    playlistButton.GroupName = "mainGroup";
                    playlistButton.Style = (Style)FindResource("PlaylistRadioButtonStyle");
                    playlistButton.Checked += new RoutedEventHandler(playlistButton_Checked);
                    playlistButton.Unchecked += new RoutedEventHandler(playlistButton_Unchecked);
                    #region Jobbklikkes menü
                    ContextMenu plsMenu = new ContextMenu();
                    MenuItem plsMenuDeleteItem = new MenuItem();
                    plsMenuDeleteItem.Header = "Lejátszási lista törlése";
                    plsMenuDeleteItem.Tag = playlistButton.Content;
                    plsMenuDeleteItem.Click += new RoutedEventHandler(plsMenuDeleteItem_Click);
                    plsMenu.Items.Add(plsMenuDeleteItem);
                    playlistButton.ContextMenu = plsMenu;
                    #endregion
                    playlistPanel.Children.Add(playlistButton);
                }
            }
        }
        void plsMenuDeleteItem_Click(object sender, RoutedEventArgs e)
        {
            playListManager.DeleteUserPlaylist((sender as MenuItem).Tag.ToString());
            RefreshPlaylistButtons();
        }
        void playlistButton_Unchecked(object sender, RoutedEventArgs e)
        {
            viewSelector.Visibility = System.Windows.Visibility.Visible;
        }
        void playlistButton_Checked(object sender, RoutedEventArgs e)
        {
            GoToPlayList(playListManager.GetUserPlayListByName((sender as RadioButton).Content.ToString()));
            viewSelector.Visibility = System.Windows.Visibility.Collapsed;
        }
        #endregion

        #region musicInfo update
        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (volumeStream != null)
            {
                if (musicInfo.trackSlider.IsMouseCaptureWithin != true)
                {
                    musicInfo.CurrentPosition = volumeStream.CurrentTime;
                }
                if (volumeStream.Position >= volumeStream.Length)
                {
                    musicControl_NextPressed(null, null);
                }
            }
            musicInfoUpdater.RunWorkerAsync();
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.Sleep(500);
        }
        #endregion

        #region Navigation
        private void zeneRadioButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!(bool)zeneRadioButton.IsChecked) zeneRadioButton.IsChecked = true; 
            GoToLocalMusicList(preferredView);
        }
        private void GoToLocalMusicList(Views newView)
        {
            playListManager.Refresh();
            preferredView = newView;
            switch (preferredView)
            {
                case Views.simpleList:
                    var localMusicPage = new LocalMusicPage(ref playListManager);
                    localMusicPage.musicDataGrid.MouseDoubleClick += new MouseButtonEventHandler(musicDataGrid_MouseDoubleClick);
                    localMusicPage.NewPlaylistAdded += new NewPlaylistAddedEventHandler(localMusicPage_NewPlaylistAdded);
                    mainFrame.Navigate(localMusicPage);
                    break;
                case Views.listWithCovers:
                    var page = new LocalMusicListAndCovers(ref playListManager);
                    page.musicListBox.MouseDoubleClick += new MouseButtonEventHandler(musicListBox_MouseDoubleClick);
                    mainFrame.Navigate(page);
                    break;
                case Views.listWithCoverFlow:
                    var page2 = new LocalMusicListAndCoverFlow(ref playListManager);
                    page2.flowControl.MouseDoubleClick += new MouseButtonEventHandler(flowControl_MouseDoubleClick);
                    page2.localPage.musicDataGrid.MouseDoubleClick += new MouseButtonEventHandler(musicDataGrid_MouseDoubleClick);
                    mainFrame.Navigate(page2);
                    break;
            }
        }

        void musicListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if ((sender as ListBox).SelectedItem != null)
            {
                currentPlaylist = (PlayList)(sender as ListBox).ItemsSource;
                currentPlaylist.playListPosition = (sender as ListBox).SelectedIndex;
                PlayTrack(currentPlaylist.CurrentTrack);
            }
        }

        void localMusicPage_NewPlaylistAdded(object sender, EventArgs e)
        {
            RefreshPlaylistButtons();
        }
        private void GoToPlayList(PlayList playList)
        {
            var localMusicPage = new LocalMusicPage(playList);
            localMusicPage.musicDataGrid.MouseDoubleClick += new MouseButtonEventHandler(musicDataGrid_MouseDoubleClick);
            mainFrame.Navigate(localMusicPage);
        }
        private void storeRadioButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!(bool)storeRadioButton.IsChecked) storeRadioButton.IsChecked = true;
            viewSelector.Visibility = System.Windows.Visibility.Hidden;
            var storePage = new StorePage();
            storePage.listenButton.Click += new RoutedEventHandler(listenButton_Click);
            mainFrame.Navigate(storePage);
        }
        void listenButton_Click(object sender, RoutedEventArgs e)
        {
            PlayMp3FromUrl((mainFrame.Content as StorePage).SelectedFilePath);
        }

        private void storeRadioButton_Unchecked(object sender, RoutedEventArgs e)
        {
            viewSelector.Visibility = System.Windows.Visibility.Visible;
        }

        #endregion

        void flowControl_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            currentPlaylist = (mainFrame.Content as LocalMusicListAndCoverFlow).pls;
            currentPlaylist.playListPosition = (mainFrame.Content as LocalMusicListAndCoverFlow).flowControl.Index;
            PlayTrack(currentPlaylist.CurrentTrack);
        }

        void musicDataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if ((sender as DataGrid).SelectedItem != null)
            {
                currentPlaylist = (PlayList)(sender as DataGrid).ItemsSource;
                currentPlaylist.playListPosition = (sender as DataGrid).SelectedIndex;
                PlayTrack(currentPlaylist.CurrentTrack);
            }
        }

        private WaveStream CreateInputStream(string fileName)
        {
            WaveChannel32 inputStream;
            if (fileName.EndsWith(".mp3"))
            {
                WaveStream mp3Reader = new Mp3FileReader(fileName);
                inputStream = new WaveChannel32(mp3Reader);
            }
            else
            {
                throw new InvalidOperationException("Unsupported extension");
            }
            volumeStream = inputStream;
            volumeStream.Volume = (float)volumeSlider.Value;
            return volumeStream;
        }

        private void CloseWaveOut()
        {
            if (waveOutDevice != null)
            {
                waveOutDevice.Stop();
            }
            if (mainOutputStream != null)
            {
                // this one really closes the file and ACM conversion
                volumeStream.Close();
                volumeStream = null;
                // this one does the metering stream
                mainOutputStream.Close();
                mainOutputStream = null;
            }
            if (waveOutDevice != null)
            {
                waveOutDevice.Dispose();
                waveOutDevice = null;
            }
        }

        private void PlayTrack(Track track)
        {
            musicInfo.Artist = track.Artist;
            musicInfo.Title = track.Title;

            mainOutputStream = CreateInputStream(track.FilePath);

            waveOutDevice.Init(mainOutputStream);
            waveOutDevice.Play();
            musicInfo.TrackLength = volumeStream.TotalTime;
            musicControl.Pause = true;
            musicInfo.LogoVisible = false;
        }

        private void PlayStream(Stream st) //nem működik rendesen, kár...
        {
            Stream ms = new MemoryStream();


            byte[] buffer = new byte[32768];
            int read;
            while ((read = st.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }

            WaveChannel32 inputStream;
            WaveStream mp3Reader = new Mp3FileReader(ms);
            inputStream = new WaveChannel32(mp3Reader);
            volumeStream = inputStream;
            volumeStream.Volume = (float)volumeSlider.Value;

            mainOutputStream = volumeStream;

            // ms.Position = 0;

            waveOutDevice.Init(mainOutputStream);
            waveOutDevice.Play();
            musicInfo.TrackLength = volumeStream.TotalTime;
            musicControl.Pause = true;
            musicInfo.LogoVisible = false;


        }

        /// <summary>
        /// Plays an mp3 file stream from a http URL
        /// </summary>
        /// <param name="url">The http url to the mp3 file</param>
        public static void PlayMp3FromUrl(string url)
        {
            var bg2 = new BackgroundWorker();
            bg2.DoWork += new DoWorkEventHandler(bg2_DoWork);
            bg2.RunWorkerAsync(url);


        }
        /// <summary>
        /// Saves a music track from the PearTunes store to the local music folder
        /// </summary>
        /// <param name="trackToGet">The track that should be saved</param>
        public static void SaveToMyCollection(Track trackToGet)
        {
            if (!succesfullLogin)
            {
                MessageBox.Show("Először jelentkezzen be");
                return;
            }
            PearTunesServiceReference.PearTunesServiceClient proxy = new PearTunesServiceReference.PearTunesServiceClient();
            proxy.Open();

            if (proxy.GetUserInfo(Properties.Settings.Default.UserName).Money < trackToGet.Price)
            {
                MessageBox.Show("Önnek nincs elég pénze a tétel megvásárlásához");
                proxy.Close();
                return;
            }
            else
            {
                proxy.BuyTrack(Properties.Settings.Default.UserName, trackToGet);
                BackgroundWorker bg3 = new BackgroundWorker();
                bg3.DoWork += new DoWorkEventHandler(bg3_DoWork);
                bg3.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg3_RunWorkerCompleted);
                bg3.RunWorkerAsync(trackToGet);
                MessageBox.Show("Letöltés folyamatban!\nKöszönjük vásárlását");
            }
            proxy.Close();



        }

        static void bg3_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("A file letöltve");
        }

        static void bg3_DoWork(object sender, DoWorkEventArgs e)
        {
            Track trackToGet = e.Argument as Track;
            PearTunesServiceReference.PearTunesServiceClient proxy = new PearTunesServiceReference.PearTunesServiceClient();


            Stream fs = System.Net.WebRequest.Create(trackToGet.FilePath).GetResponse().GetResponseStream();
            string filename = trackToGet.Artist + "-" + trackToGet.Title;
            
            ConvertToValidFileName(ref filename);
            string saveTo = Properties.Settings.Default.localMusicPath + "\\" + filename+".mp3";
            // create a write stream
            FileStream writeStream = new FileStream(saveTo, FileMode.Create, FileAccess.Write);
            // write to the stream
            
            ReadWriteStream(fs, writeStream);


            proxy.Close();
        }

        private static void ConvertToValidFileName(ref string saveTo)
        {
            var invalidchars = System.IO.Path.GetInvalidFileNameChars();
            for (int i = 0; i < invalidchars.Length; i++)
			{
                saveTo = saveTo.Replace(invalidchars[i], '_');
            }
        }

        private static void ReadWriteStream(Stream readStream, Stream writeStream)
        {
            int Length = 256;
            Byte[] buffer = new Byte[Length];
            int bytesRead = readStream.Read(buffer, 0, Length);
            // write the required bytes
            while (bytesRead > 0)
            {
                writeStream.Write(buffer, 0, bytesRead);
                bytesRead = readStream.Read(buffer, 0, Length);
            }
            readStream.Close();
            writeStream.Close();
        }

        static void bg2_DoWork(object sender, DoWorkEventArgs e)
        {

            string url = e.Argument as string;

            using (Stream ms = new MemoryStream())
            {
                using (Stream stream = System.Net.WebRequest.Create(url)
                    .GetResponse().GetResponseStream())
                {
                    byte[] buffer = new byte[32768];
                    int read;
                    while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        ms.Write(buffer, 0, read);
                    }
                }

                ms.Position = 0;
                using (WaveStream blockAlignedStream =
                    new BlockAlignReductionStream(
                        WaveFormatConversionStream.CreatePcmStream(
                            new Mp3FileReader(ms))))
                {
                    using (WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
                    {
                        waveOut.Init(blockAlignedStream);
                        waveOut.Play();
                        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                        sw.Start();
                        while (waveOut.PlaybackState == PlaybackState.Playing && sw.ElapsedMilliseconds < 10000)
                        {
                            System.Threading.Thread.Sleep(100);
                        }
                        sw.Stop();
                        waveOut.Stop();
                    }
                }
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            zeneRadioButton.IsChecked = true;
            LoginUser();

        }
        /// <summary>
        /// Checks if the user is registerd in the online database
        /// </summary>
        public static void LoginUser()
        {
            BackgroundWorker bg4 = new BackgroundWorker();
            bg4.DoWork += new DoWorkEventHandler(bg4_DoWork);
            bg4.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg4_RunWorkerCompleted);
            bg4.RunWorkerAsync();
        }

       static void bg4_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!(bool)e.Result)
            {
                MessageBox.Show("Hibás felhasználónév és/vagy jelszó");
                succesfullLogin = false;
            }
            else
            {
                succesfullLogin = true;
            }
        }

        static void bg4_DoWork(object sender, DoWorkEventArgs e)
        {
            PearTunesServiceClient proxy = new PearTunesServiceClient();
            proxy.Open();
            e.Result = proxy.ValidateUser(Properties.Settings.Default.UserName, Properties.Settings.Default.Password);


            proxy.Close();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            CloseWaveOut();
        }

        private void volumeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (volumeStream != null)
                volumeStream.Volume = (float)volumeSlider.Value;

        }

        void trackSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if ((sender as Slider).IsMouseCaptureWithin == true)
            {
                mainOutputStream.Position = (long)(sender as Slider).Value * 355000;
            }
        }

        #region musicControl events
        private void musicControl_PausePressed(object sender, RoutedEventArgs e)
        {
            waveOutDevice.Pause();
            musicControl.Pause = false;
        }
        private void musicControl_PlayPressed(object sender, RoutedEventArgs e)
        {

            if (waveOutDevice != null && currentPlaylist != null)
            {
                waveOutDevice.Play();
                musicControl.Pause = true;
            }
        }
        private void musicControl_NextPressed(object sender, RoutedEventArgs e)
        {
            if (currentPlaylist != null)
                if (currentPlaylist.NextTrack())
                {
                    PlayTrack(currentPlaylist.CurrentTrack);
                }
                else
                {
                    musicControl_PausePressed(null, null);
                }
        }
        private void musicControl_PrevPressed(object sender, RoutedEventArgs e)
        {
            if (currentPlaylist != null)
                if (currentPlaylist.PreviousTrack())
                {
                    PlayTrack(currentPlaylist.CurrentTrack);
                }
        }

        #endregion

        #region ViewSelector cuccok

        void coverflowSelect_MouseDown(object sender, MouseButtonEventArgs e)
        {
            GoToLocalMusicList(Views.listWithCoverFlow);
        }

        void listwithcoverSelect_MouseDown(object sender, MouseButtonEventArgs e)
        {
            GoToLocalMusicList(Views.listWithCovers);
        }

        void listSelect_MouseDown(object sender, MouseButtonEventArgs e)
        {
            GoToLocalMusicList(Views.simpleList);
        }

        #endregion

        #region Menu stuff
        private void SettingsMenuItem_Click(object sender, RoutedEventArgs e)
        {
            UserSettingsForm form = new UserSettingsForm();
            form.Owner = this;
            if (form.ShowDialog() == true)
            {
                playListManager = new PlayListManager();
                GoToLocalMusicList(preferredView);
                RefreshPlaylistButtons();
            }
        }
        private void ExitMenuItem_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
        #endregion





    }
}
